import basicTypes.C4Constant;
import Prism.core.Architecture;
import Prism.core.Component;
import Prism.core.Connector;
import Prism.core.Port;
import Prism.core.PrismConstants;
import Prism.extensions.port.ExtensiblePort;
import Prism.extensions.port.distribution.SocketDistribution;

import component.NossDatabase;
import component.NossTransManager;


public class Noss {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		nossDatabaseServerStart();
		nossTransManagerStart();
	}

	// nossDatabaseServer Program 
	public static void nossDatabaseServerStart() {
		Architecture nossDatabaseServerArchitecture = new Architecture();
        
        // Create nossDatabase Component
    	Component nossDatabaseComponent = new Component();
    	
		// Create nossDatabase Component's implementation
    	nossDatabaseComponent.setImplementation(new NossDatabase());
		
	/*
	 * Server Setup
	 */
		// Add a port to the nossDatabase for reply requests.
		Port nossDatabaseReplyPort = new Port(PrismConstants.REPLY);
		nossDatabaseComponent.addPort(nossDatabaseReplyPort);
		
		// Add nossDatabaseComponent to nossDatabaseServerArchitecture
		nossDatabaseServerArchitecture.add(nossDatabaseComponent);
		
		// Create a connector(nossDatabaseConn) for lower layer components
		Connector nossDatabaseConnServer = new Connector();
		
		// Add a port to the nossDatabaseConn for forwarding requests.
		Port nossDatabaseConnRequestPort = new Port(PrismConstants.REQUEST);
		nossDatabaseConnServer.addPort(nossDatabaseConnRequestPort);
		
		// nossDatabaseConn is extensiblePort because nossDatabase and lower layer's components are separated
		// because scale easily by adding more servers, also enhance performance
		ExtensiblePort nossDatabaseConnReplyPort = new ExtensiblePort (PrismConstants.REPLY);
		nossDatabaseConnReplyPort.addDistribution(new SocketDistribution(C4Constant.nossDatabasePort));           
		nossDatabaseConnServer.addPort(nossDatabaseConnReplyPort);
		
        // Add the BillingSystemConn to the nossDatabaseServerArchitecture
		nossDatabaseServerArchitecture.add(nossDatabaseConnServer);
		
		// Weld the request port to the connector reply port.
		nossDatabaseServerArchitecture.weld(nossDatabaseReplyPort, nossDatabaseConnRequestPort);
		
		
	// Start this Architecture
		nossDatabaseServerArchitecture.start();
	}
	
	public static void nossTransManagerStart() {
		
		// Create Architecture
		Architecture nossTransManagerArchitecture = new Architecture();
		
		// Create Implementation
		NossTransManager nossTransManager = new NossTransManager();
	
        // Create nossTransManager Component
    	Component nossTransManagerComponent = new Component();
		
		// Create nossTransManager Component's implementation
    	nossTransManagerComponent.setImplementation(nossTransManager);
        
		
	/*
	 * Server Setup
	 */
  
		// Add a port to the nossTransManager for reply requests.
		Port nossTransManagerReplyPort = new Port(PrismConstants.REPLY);
		nossTransManagerComponent.addPort(nossTransManagerReplyPort);
		
		// Add nossTransManagerComponent to nossTransManagerArchitecture
		nossTransManagerArchitecture.add(nossTransManagerComponent);
		
		// Create a connector(nossTransManagerConn)
		Connector nossTransManagerConnServer = new Connector();
		
		// Add a port to the nossTransManagerConn for forwarding requests.
		Port nossTransManagerConnRequestPort = new Port(PrismConstants.REQUEST);
		nossTransManagerConnServer.addPort(nossTransManagerConnRequestPort);
		
		// nossTransManagerConn is extensiblePort because noss and onlineDB and TransConsistCheck(in C4) are connected by network 
		ExtensiblePort nossTransManagerConnReplyPort = new ExtensiblePort (PrismConstants.REPLY);
		nossTransManagerConnReplyPort.addDistribution(new SocketDistribution(C4Constant.nossTransManagerPort));           
		nossTransManagerConnServer.addPort(nossTransManagerConnReplyPort);
		
        // Add the BillingSystemConn to the c4Architecture
		nossTransManagerArchitecture.add(nossTransManagerConnServer);
		
		// Weld the GUI request port to the connector reply port.
		nossTransManagerArchitecture.weld(nossTransManagerReplyPort, nossTransManagerConnRequestPort);
	
	/*
	 * Client Setup
	 */
		
		// Add a port to the nossTransManager for sending requests.
		Port nossTransManagerRequestPort = new Port(PrismConstants.REQUEST);
		nossTransManagerComponent.addPort(nossTransManagerRequestPort);
        
		// Create a connector(offLineDatabaseConn) for nossTransManager
		Connector nossDatabaseConnClient = new Connector();

		// Add a port to the offLineDatabaseConn for receiving requests.
		Port nossDatabaseConnReplyPort = new Port(PrismConstants.REPLY);
		nossDatabaseConnClient.addPort(nossDatabaseConnReplyPort);

		// nossDatabaseConn is extensiblePort because nossDatabase connects nossTransManager by network
		// For scalable performance and its storage and reliability by adding more servers
		ExtensiblePort nossDatabaseConnRequestPort = new ExtensiblePort (PrismConstants.REQUEST);
		nossDatabaseConnRequestPort.addDistribution(new SocketDistribution());           
		nossDatabaseConnClient.addPort(nossDatabaseConnRequestPort);
		
        // Add the offLineDatabaseConn to the billingServerArchitecture
		nossTransManagerArchitecture.add(nossDatabaseConnClient);
		
		// Weld the request port to the connector reply port.
		nossTransManagerArchitecture.weld(nossTransManagerRequestPort, nossDatabaseConnReplyPort);
		/* 
		 * Client Ends
		 */
		
		// Start this Architecture
		nossTransManagerArchitecture.start();

		// Connect the connector request port to the nossDatabaseConn.
		nossDatabaseConnRequestPort.connect(C4Constant.hostname, C4Constant.nossDatabasePort);
		
		// Initialize numbers
		nossTransManager.getNumbers();
		}
	
}
